package com.example.shirodemo.config;

import com.example.shirodemo.dao.MysqlSessionDao;
import com.example.shirodemo.realm.MyRealm;
import com.example.shirodemo.realm.SecondRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import java.util.*;

/**
 * ShiroTest   com.example.shirodemo.config
 *
 * @author：黄玉刚 -成都电安惠科有限公司
 * @date： 2019/11/30 20:26
 * @Description ：
 */
@Configuration
public class ShiroConfig {
    @Bean
    public MysqlSessionDao mysqlSessionDao() {
        return new MysqlSessionDao();
    }

    //设置session管理器
    @Bean(name = "sessionManager")
    public DefaultWebSessionManager sessionManager() {

        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        SimpleCookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
        cookie.setHttpOnly(true);
        cookie.setMaxAge(24 * 60 * 60);

        sessionManager.setSessionIdCookie(cookie);
        sessionManager.setDeleteInvalidSessions(true);//设置是否删除无效session
        //sessionManager.setGlobalSessionTimeout(mysqlSessionDao().getExpireTime());//设置全局session超时时长
        //mysqlSessionDao().setCacheManager(mysqlCacheManager());
        sessionManager.setSessionDAO(mysqlSessionDao());//设置自定义session操作

        //sessionManager.setSessionValidationSchedulerEnabled(true);//设置是否定期检查session
        return sessionManager;
    }

    @Bean
    HashedCredentialsMatcher md5matcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("MD5");
        matcher.setHashIterations(5);
        return matcher;
    }

    @Bean
    HashedCredentialsMatcher sha1matcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("SHA1");
        matcher.setHashIterations(5);
        return matcher;
    }

    @Bean
    MyRealm myRealm() {
        MyRealm my = new MyRealm();
        //自定义的令牌RealM

        my.setCredentialsMatcher(md5matcher());
        return my;
    }

    @Bean
    SecondRealm myRealm2() {
        SecondRealm my = new SecondRealm();
        //自定义的令牌RealM

        my.setCredentialsMatcher(sha1matcher());
        return my;
    }

    @Bean
    SecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        List<Realm> list = new LinkedList<>();
        list.add(myRealm());
        list.add(myRealm2());
        manager.setRealms(list);
        //    manager.setAuthenticator(modularRealmAuthenticator());
        manager.setSessionManager(sessionManager());
        return manager;
    }

    @Bean
    ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager());
        bean.setLoginUrl("/login");
        bean.setSuccessUrl("/index");
        bean.setUnauthorizedUrl("/unauthorerror");
        Map<String, String> map = new LinkedHashMap<>();
        map.put("/doLogin", "anon");

        map.put("/**", "authc");
        bean.setFilterChainDefinitionMap(map);
        return bean;
    }

    /**
     * 系统自带的Realm管理，主要针对多realm
     */
    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator() {
        ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
        //至少有一个验证成功就成功
        modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());

        return modularRealmAuthenticator;
    }

    /**
     * 开启Shiro注解(如@RequiresRoles,@RequiresPermissions),
     * 需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 开启shiro aop注解支持.
     * 使用代理方式;所以需要开启代码支持;
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean(name = "simpleMappingExceptionResolver")
    public SimpleMappingExceptionResolver
    createSimpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
        Properties mappings = new Properties();
        //数据库异常处理
        mappings.setProperty("DatabaseException", "/databaseError");
        mappings.setProperty("UnauthorizedException", "/unauthorerror");
        // None by default
        r.setExceptionMappings(mappings);
        // 访问错误，直接访问登录页面
        r.setDefaultErrorView("/base/login");
        // Default is "exception"
        r.setExceptionAttribute("ex");

        return r;
    }

}
